

from typing import Dict, List

from common import market_to_str, tick_time_to_hm, tick_time_to_ymd, tick_time_to_ymdhm
from x_com import source_api
from x_com.import_api import realtime_kdata_service_0_0_1
from x_com.source_api import MinOrDayData


class RTDataInfo:
    # 格式 {市场}.{代码}
    order_book_id: str
    # 当前合成的分钟线数据
    rt_min_datas: List[MinOrDayData]
    # 最后一根bar
    cur_rt_data: realtime_kdata_service_0_0_1.RTTickData

    # 初始化对象
    def __init__(self, order_book_id: str) -> None:
        self.cur_rt_data = None
        self.rt_min_datas = []
        self.order_book_id = order_book_id

    def merge_tick_to_min_inner(
        self,
            last_tick_data: realtime_kdata_service_0_0_1.RTTickData,
            tick_data:  realtime_kdata_service_0_0_1.RTTickData,
            min_data: source_api.MinOrDayData):

        # 当前分钟的最高价，小于tick价，这用tick价格，更新最高价
        if min_data.high < tick_data.last:
            min_data.high = tick_data.last

        # 当前分钟的最低价，大于tick价，这用tick价格，更新最低价
        if min_data.low > tick_data.last:
            min_data.low = tick_data.last

        # 当前分支的收盘价，为最新的 tick 价格
        min_data.close = tick_data.last
        # min_data.open_interest = tick_data.open_interest
        if last_tick_data is not None:
            min_data.volume += tick_data.volume - last_tick_data.volume
            # min_data.total_turnover += tick_data.total_turnover - last_tick_data.total_turnover

    def tick_to_min_data(
            self,
            last_tick_data: realtime_kdata_service_0_0_1.RTTickData,
            tick_data: realtime_kdata_service_0_0_1.RTTickData,
            tick_bar_ymdhm: int) -> source_api.MinOrDayData:
        
        min_data = source_api.MinOrDayData()
        min_data.datetime = tick_bar_ymdhm
        min_data.open = tick_data.last
        min_data.high = tick_data.last
        min_data.low = tick_data.last
        min_data.close = tick_data.last
        # min_data.open_interest = tick_data.open_interest

        if last_tick_data is not None:
            min_data.volume = tick_data.volume - last_tick_data.volume
            # min_data.total_turnover = tick_data.total_turnover - last_tick_data.total_turnover
        else:
            min_data.volume = tick_data.volume
            # min_data.total_turnover = tick_data.total_turnover

        return min_data

    def data_in(self, tick_data: realtime_kdata_service_0_0_1.RTTickData):
        tick_bar_ymdhm = tick_time_to_ymdhm(f"{tick_data.datetime}")

        
        # 
        if len(self.rt_min_datas) == 0:
            min_data = self.tick_to_min_data(
                self.cur_rt_data, tick_data, tick_bar_ymdhm)
            self.rt_min_datas.append(min_data)
        else:
            # 最后当前的 min 数据
            last_min_data = self.rt_min_datas[-1]
            # 在同一分钟内，则合成
            if last_min_data.datetime == tick_bar_ymdhm:
                self.merge_tick_to_min_inner(
                    self.cur_rt_data, tick_data, last_min_data)
            else:
                # 不在同一分钟内，和合成新的数据
                min_data = self.tick_to_min_data(
                    self.cur_rt_data, tick_data, tick_bar_ymdhm)
                self.rt_min_datas.append(min_data)

        hm = tick_time_to_hm(f"{tick_data.datetime}")

        # 说明当天数据已经接受完成，持久化
        if hm == 1500:
            ymd = tick_time_to_ymd(f"{tick_data.datetime}")
            file_name = f"{SERVICE.csv_file_path}/{self.order_book_id}_{ymd}.csv"
            with open(file_name, 'w', encoding="utf-8") as file_writer:
                file_writer.write("datetime, open, high, low, close, volume\n")

                for rt_min_data in self.rt_min_datas:
                    file_writer.write(f"{rt_min_data.datetime}, {rt_min_data.open}, {rt_min_data.high}, {rt_min_data.low}, {rt_min_data.close}, {rt_min_data.volume}\n")
            
        self.cur_rt_data = tick_data


# 实时行情持有者
class RTDataHolder:
    receive_num:int
    rt_data_dict: Dict[str, RTDataInfo]

    def __init__(self) -> None:
        self.receive_num = 0
        self.rt_data_dict = {}

    def tick_in(self, tick_datas: realtime_kdata_service_0_0_1.RTTickDatas):
    
        # 如果为 0 则返回
        if len(tick_datas.datas) == 0:
            return

        # 转成 转成 {市场}.{代码} 的格式，因为 tick_datas 下所有的数据，都是同一个代码的，因此通过第一个元素获取即可
        # self.receive_num += 1
        first_data = tick_datas.datas[0]
        market_str = market_to_str(first_data.market)
        order_book_id = f"{market_str}.{first_data.code}"

        # 使用 setdefault 当元素存在，则获取之前的元素，当元素不存在，则创建
        rt_data_info = self.rt_data_dict.setdefault(
            order_book_id, RTDataInfo(order_book_id))

        # 循环处理数据
        for tick_data in tick_datas.datas:
            rt_data_info.data_in(tick_data)

    def get_min_data(self, order_book_id:str)-> List[MinOrDayData]:
      rt_data_info = self.rt_data_dict.get(order_book_id)
      if rt_data_info is None:
          return []
      return rt_data_info.rt_min_datas
      
    def clear_min_data(self, order_book_id: str):
      self.rt_data_dict.pop(order_book_id, None)